package cn.tb.basic.service.impl;

import cn.tb.basic.constants.BaseConstants;
import cn.tb.basic.dto.RegisterDto;
import cn.tb.basic.exception.BusinessException;
import cn.tb.basic.service.IVerifyCodeService;
import cn.tb.basic.util.StrUtils;
import cn.tb.basic.util.VerifyCodeUtils;
import cn.tb.user.domain.User;
import cn.tb.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;

    @Resource
    private UserMapper userMapper;
    /**
     *  图形验证码获取流程
     *        (每次都是直接生成新的，但是要覆盖前面的)
     *        1.生成code
     *         String code = StrUtils.getComplexRandomString(4);
     *        2.保存redis，设置过期时间  key是什么==前端请求给我传递的UUID
     *         redisTemplate.opsForValue().set(
     *                 key,//前端传递的UUID
     *                 code, //图片中的码儿
     *                 5,//过期时间
     *                 TimeUnit.MINUTES);//过期时间的单位
     *         3.把图使用Base64编码成字符串
     *         4.返回Base64编码的字符串
     * @param key
     * @return
     */
    /**
     * 图片验证码
     * @param key
     * @return
     */
    @Override
    public String imgCode(String key) {
        if(!StringUtils.hasLength(key)){
            throw new BusinessException("key值不能为空！");
        }
        //生成code
        String code = StrUtils.getComplexRandomString(4);
        //保存到redis，设置过期的时间
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //用Base64编码成字符串，返回Base64编码的字符串
        return VerifyCodeUtils.VerifyCode(100,40,code);
    }

    /**
     * 邮箱图片验证码
     * @param key
     * @return
     */
    @Override
    public String emailImgCode(String key) {
        if(!StringUtils.hasLength(key)){
            throw new BusinessException("key值不能为空！");
        }
        //生成code
        String code = StrUtils.getComplexRandomString(6);
        //保存到redis，设置过期的时间
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //用Base64编码成字符串，返回Base64编码的字符串
        return VerifyCodeUtils.VerifyCode(100,40,code);
    }

    /**
     * 发送短信验证码 注册和微信绑定共用
     * @param dto
     */
    @Override
    public void smsCode(RegisterDto dto){

        String type = dto.getType();

        if(StringUtils.isEmpty(type)){
            throw new BusinessException("type不能为空");
        }
        if(type.equals("register")){
            registerCode(dto);
        }else if(type.equals("binder")){
            binderCode(dto);
        }else if(type.equals("login")){
            loginCode(dto);
        }
    }

    /**
     * 手机验证码登录
     * @param dto
     */
    private void loginCode(RegisterDto dto) {
        String phone = dto.getPhone();
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("电话号码不能为空！！");
        }
        String businessKey = BaseConstants.RegisterConstants.LOGIN_SMS_PREFIX+dto.getPhone();
        sendSmsCode(businessKey);
    }


    /**
     * 注册短信验证码
     * @param dto
     * @return
     */
    public void registerCode(RegisterDto dto) {
        String phone = dto.getPhone();
        String imageCodeValue = dto.getImageCodeValue();
        String imageCodeKey = dto.getImageCodeKey();
        //1.空校验
        if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(imageCodeValue)||StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("参数异常！！");
        }
        //2.判断图形验证码是否一致,根据imageCodeKey从Redis中获取
        Object imgCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        //2.1获取到了,跟前端填写的图片验证码做比较
        if(imgCodeTmp.toString().equals(imageCodeValue)){
            throw new BusinessException("验证码错误！！！");
        }
        //2.2获取不到，验证码过期
        if(imgCodeTmp==null){
            throw new BusinessException("验证码已经过期，请重新获取！！！");
        }
        //3.判断手机号是否注册过
        User userTmp = userMapper.loadByPhone(phone);
        //3.1注册过了
        if(userTmp!=null){
            throw new BusinessException("用户已经存在，请直接登录！");
        }
        //3.2没注册就下一步
        String businessKey = BaseConstants.RegisterConstants.REGISTER_SMS_PREFIX+phone;
        sendSmsCode(businessKey);
    }

    /**
     * 微信绑定验证码
     * @param dto
     */
    private void binderCode(RegisterDto dto) {
        String businessKey = BaseConstants.RegisterConstants.BINDER_SMS_PREFIX+dto.getPhone();
        sendSmsCode(businessKey);
    }


    /**
     * 发送短信验证码
     * @param businessKey
     */
    private void sendSmsCode(String businessKey){
            //4.短信验证码
            //根据电话号码拼接key,从Redis中获取曾经可能有的短信验证码
            String key = businessKey;
            Object smsCodeTmp = redisTemplate.opsForValue().get(key);
            String smsCode = "";
            //4.1 获取到了,校验是否超过重发时间
            if(smsCodeTmp!=null){
                Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
                //4.1.1重发时间还没到
                if(System.currentTimeMillis()-oldTime <= 1*60*1000){
                    throw new BusinessException("重发时间还没到1分钟，你在干什么？");
                }
                //4.2.2重发时间到了，但是验证码还没有过期
                smsCode = smsCodeTmp.toString().split(":")[0];

                //4.2 获取不到,生成新的短信验证码
            }else {
                //生成验证码
                smsCode = StrUtils.getComplexRandomString(4);
            }

            //5 存储Redis，并设置一个过期时间
            String smsCodeValue = smsCode+":"+System.currentTimeMillis();
            redisTemplate.opsForValue().set(key,smsCodeValue,3, TimeUnit.MINUTES);
            //6 发送短信
            //SmsUtils.sendSms(dto.getPhone(),"亲，您的短信验证码是："+smsCode+"，三分钟之内有效哦！");
            System.out.println("亲，您的短信验证码是："+smsCode+"，三分钟之内有效哦！");
        }

    /**
     * 邮箱验证码
     * @param dto
     */
    @Override
    public void emailCode(RegisterDto dto) {
        //1.空校验
        String email = dto.getEmail();
        String emailImageCodeKey = dto.getEmailImageCodeKey();
        String emailImageCodeValue = dto.getEmailImageCodeValue();
        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(emailImageCodeKey)||StringUtils.isEmpty(emailImageCodeValue)){
            throw new BusinessException("参数异常！！");
        }
        //2.判断图形验证码是否一致
        Object imgCodeTmp = redisTemplate.opsForValue().get(emailImageCodeKey);
        //2.1获取到了,跟前端填写的图片验证码做比较
        if(imgCodeTmp.toString().equals(emailImageCodeValue)){
            throw new BusinessException("验证码错误！！！");
        }
        //2.2获取不到，验证码过期
        if(imgCodeTmp==null){
            throw new BusinessException("验证码已经过期，请重新获取！！！");
        }
        //3.判断邮箱是否注册过
        User userTmp = userMapper.loadByEmail(email);
        //3.1注册过了
        if(userTmp!=null){
            throw new BusinessException("用户已经存在，请直接登录！");
        }
        //3.2没注册就下一步
        //4.邮箱验证码
        //根据邮箱号码拼接key,从Redis中获取曾经可能有的短信验证码
        String key = BaseConstants.RegisterConstants.REGISTER_SMS_PREFIX +email;
        Object emailCodeTmp = redisTemplate.opsForValue().get(key);
        String emailCode = "";
        //4.1 获取到了,校验是否超过重发时间
        if(emailCodeTmp!=null){
            Long oldTime = Long.valueOf(emailCodeTmp.toString().split(":")[1]);
            //4.1.1重发时间还没到
            if(System.currentTimeMillis()-oldTime <= 1*60*1000){
                throw new BusinessException("重发时间还没到1分钟，你在干什么？");
            }
            //4.2.2重发时间到了，但是验证码还没有过期
            emailCode = emailCodeTmp.toString().split(":")[0];

            //4.2 获取不到,生成新的短信验证码
        }else {
            //生成验证码
            emailCode = StrUtils.getComplexRandomString(4);
        }

        //5 存储Redis，并设置一个过期时间
        String emailCodeValue = emailCode+":"+System.currentTimeMillis();
        redisTemplate.opsForValue().set(key,emailCodeValue,3, TimeUnit.MINUTES);
        //6 发送短信
//        SimpleMailMessage message = new SimpleMailMessage();
//        //设置发送人
//        message.setFrom("2798580754@qq.com");
//        //邮件主题
//        message.setSubject("注册");
//        //邮件内容
//        message.setText("亲，您的验证码："+emailCode);
//        //收件人
//        //message.setTo(employee.getEmail());
//        message.setTo(email);
//        javaMailSender.send(message);
        System.out.println("亲，您的短信验证码是："+emailCode+"，三分钟之内有效哦！");
    }


}
